package com.interview.three;

import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;

/**
 * 通过 引入队列解决 ThreadLocalMap 内存泄漏问题
 * 但是为啥 ThreadLocalMap 没有用呢，因为成本问题
 */
public class TestWeakMap {
    public static void main(String[] args) {
        MyWeakMap map = new MyWeakMap();
        map.put(0,new String("a"),"0");
        map.put(1,"b","1");
        map.put(2,new String("c"),"2");
        map.put(3,new String("d"),"3");
        System.out.println(map);
        
        System.gc();

        // [null:0,null:1,null:2,null:3,] 内存泄漏了。val 没有被回收
        System.out.println(map);
        map.clean();

        System.out.println(map);
        
    }
    
    static class MyWeakMap{
        static ReferenceQueue<String> queue =new ReferenceQueue<>();
        static class Entry extends WeakReference<String>{
            String value;
            public Entry(String key,String value){
                super(key,queue);
                this.value =value;
            }
        }
        Entry[] table = new Entry[4];
        public void put(int idx,String key,String val){
            table[idx] = new Entry(key,val);
        }
        public void clean(){
            Object ret;
            while ((ret =queue.poll())!=null){
                for (int i = 0; i < table.length; i++) {
                    if (table[i] == ret){
                        table[i] = null;
                    }
                }
            }
        }
        public String get(String key){
            for (Entry entry : table) {
                if (entry !=null){
                    String k = entry.get();
                    if (k!=null && k.equals(key)){
                        return entry.value;
                    }
                }
            }
            return null;
        }

        @Override
        public String toString() {
            StringBuilder s= new StringBuilder("[");
            for (Entry entry : table) {
                if (entry!=null){
                    s.append(entry.get()).append(":").append(entry.value).append(",");
                }
            }
            return s+"]";
        }
    }
}
